package com.imooc.security.browser;

import com.imooc.security.core.properties.SecurityProperties;
import com.imooc.security.core.validate.code.ValidateCodeFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * Created by zghgchao 2018/4/20 21:47
 */
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private SecurityProperties securityProperties;

    @Autowired
    private AuthenticationSuccessHandler imoocAuthenticationSuccessHandler;//将自己定义的表单登录处理器注入进来

    @Autowired
    private AuthenticationFailureHandler imoocAuthenticationFailureHandler;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
//        tokenRepository.setCreateTableOnStartup(true);//在启动的时候创建表，第二次启动时注释调
        return tokenRepository;
    }



    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        http.httpBasic()//httpBasic形式登录
        /*http.formLogin()//指定表单登录类型
                .and()
                .authorizeRequests()//求请求进行授权
                .anyRequest()//对于任何请求
                .authenticated();//都需要身份认证*/

        /*http.formLogin()
                .loginPage("/imooc-signIn.html")
                .loginProcessingUrl("/authentication/from")//表单提交后，UsernamePasswordAuthenticationFilter根据配置的地址进行拦截，并在这个请求里获取用户名和密码
                .and()
                .authorizeRequests()
                .antMatchers("/imooc-signIn.html").permitAll()//当访问imooc-signIn是不需要身份认证
                .anyRequest()
                .authenticated()
                .and().csrf().disable();//关掉csrf:关闭跨站伪造请求防护*/

        ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
        validateCodeFilter.setAuthenticationFailureHandler(imoocAuthenticationFailureHandler);//设置验证失败时的过滤器
        validateCodeFilter.setSecurityProperties(securityProperties);//
        validateCodeFilter.afterPropertiesSet();//

        //将自定义的图片验证过滤器 添加到 UsernamePasswordAuthenticationFilter之前执行
        http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
                .formLogin()
                .loginPage("/authentication/require")
                .loginProcessingUrl("/authentication/from")//表单提交后，UsernamePasswordAuthenticationFilter根据配置的地址进行拦截，并在这个请求里获取用户名和密码
                .successHandler(imoocAuthenticationSuccessHandler)//指定表单登录成功处理器
                .failureHandler(imoocAuthenticationFailureHandler)//指定登录失败处理器
                .and()  // ---->进行rememberMe认证
                .rememberMe()
                .tokenRepository(persistentTokenRepository())
                .tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds())
                .userDetailsService(userDetailsService)
                .and() //---->进行身份认证
                .authorizeRequests()
                .antMatchers("/authentication/require"
                        ,securityProperties.getBrowser().getLoginPage()
                        ,"/code/image").permitAll()//当这些时是不需要身份认证的
                .anyRequest()
                .authenticated()
                .and().csrf().disable();//关掉csrf:关闭跨站伪造请求防护
    }
}
